'use strict';

const { Service } = require('egg');
const xml2json = require('xml2json');
const https = require('https');
const crypto = require('crypto');

class MpService extends Service {
  solve() {
    const { ctx } = this;
    return new Promise((resolve, reject) => {
      const json = JSON.parse(xml2json.toJson(ctx.request.body, {}));
      const { xml } = json;
      const { MsgType } = xml;
      switch (MsgType) {
        case 'voice':
          xml.Content = xml.Recognition;
          // fall through
        case 'text': {
          const { Content } = xml;
          console.log(Content);
          const appId = '5f16c2fd';
          const apiKey = '61291e769d947032b765b571b45b0c42';
          const time = (Number(new Date()) / 1000).toFixed(0);
          const authId = '2f11ca26bc4138766ca21a7447c8d2d8';
          const params = {
            scene: 'main',
            auth_id: authId,
            data_type: 'text',
          };
          const xParams = Buffer.from(JSON.stringify(params)).toString('base64');
          const checkSum = crypto.createHash('md5').update(apiKey + time + xParams).digest('hex');
          const request = https.request('https://openapi.xfyun.cn/v2/aiui', {
            headers: {
              'X-Appid': appId,
              'X-CurTime': time,
              'X-Param': xParams,
              'X-CheckSum': checkSum,
            },
            method: 'POST',
          }, res => {
            if (res.statusCode >= 200 && res.statusCode < 300) {
              let str = '';
              res.on('data', chunk => { str += chunk; });
              res.on('end', () => {
                const reply = JSON.parse(str);
                const { data } = reply;
                const { intent } = data[0];
                const { answer } = intent;
                const { text } = answer;
                if (text[0] === '{') {
                  const obj = JSON.parse(text);
                  console.log(obj);
                  switch (obj.type) {
                    case 'article':
                      ctx.service.news.pick(new Date(obj.date)).then(value => resolve(value)).catch(reason => reject(reason));
                      break;
                    case 'search':
                      ctx.service.news.search(obj.str).then(value => resolve(value)).catch(reason => reject(reason));
                      break;
                    case 'notice': {
                      const dt = new Date(obj.date);
                      if (new Date(Number(new Date()) + 172800000) > dt) {
                        const { FromUserName } = xml;
                        ctx.service.custom.notify(FromUserName, obj.str, dt);
                        resolve('已设置在' + (dt).toLocaleString() + '提醒您' + obj.str);
                      } else {
                        reject(new Error('根据微信订阅号的回复限制，仅可设置48小时内的提醒'));
                      }
                      break;
                    }
                    default:
                      reject(new Error('Malformed type'));
                      break;
                  }
                } else {
                  resolve(text);
                }
              });
            } else {
              reject(new Error('HTTP' + res.statusCode));
            }
          });
          request.write(Content, error => {
            if (error) {
              reject(error);
            }
          });
          request.end();
          break;
        }
        default: resolve('success'); break;
      }
    });
  }
}

module.exports = MpService;
